package br.ufrn.cerescaico.sepe.bo;

import br.ufrn.cerescaico.sepe.Sepe;
import br.ufrn.cerescaico.sepe.beans.Perfil;
import br.ufrn.cerescaico.sepe.beans.Usuario;
import br.ufrn.cerescaico.sepe.dao.Dao;
import br.ufrn.cerescaico.sepe.dao.UsuarioDao;
import br.ufrn.cerescaico.sepe.dao.util.DataAccessLayerException;
import java.util.List;
import org.apache.log4j.Logger;

/**
 * Classe de negócio do bean Usuário do sistema Sepe.
 * @author Taciano Morais Silva
 * @version 16/08/2010, 18h30m
 * @since 16/08/2010, 18h30m
 */
public class UsuarioBO extends AbstractBO {

    /**
     * Logger.
     */
    private Logger logger = Logger.getLogger(UsuarioBO.class);

    /**
     * 
     * @param Sepe
     */
    public UsuarioBO(Sepe Sepe) {
        super(Sepe);
    }

    /**
     * Autentica o usuários. Se não for possível autenticar o usuário será
     * retornado <code>null</code>.
     * @param username Login do usuário.
     * @param password Senha do usuário.
     * @return O usuário autenticado, ou <code>null</code> caso contrário.
     * @throws SepeException Casp ocorra algum erro de acesso ao banco.
     */
    public Usuario autenticar(String username, String password) throws SepeException {
        try {
            UsuarioDao dao = new UsuarioDao();
            return dao.autenticar(username, password);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.usuario.bo.autenticar", ex);
        }
    }

    /**
     * Lista todos os usuários cadastrados no sistema.
     * @return A lista de usuários.
     */
    public List<Usuario> listar() throws SepeException {
        try {
            Dao<Usuario> dao = new UsuarioDao();
            return dao.findAll();
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.usuario.bo.listar", ex);
        }
    }

    /**
     * Busca o usuário a partir do seu identificador.
     * @param id O identificador do usuário.
     * @return O usuário localizado.
     */
    public Usuario buscar(Integer id) throws SepeException {
        try {
            Dao<Usuario> dao = new UsuarioDao(getSepe());
            return dao.find(id);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.usuario.bo.buscar", ex);
        }
    }

    /**
     * Incluir usuário no sistema.
     * @param usuario O usuário a ser incluído.
     */
    public void incluir(Usuario usuario) throws SepeException {
        verificarNull(usuario);
        verificarLoginExistente(usuario);
        try {
            //verificarTamMin("login", usuario.getLogin());
            //verificarTamMin("nome", usuario.getNome());

            Dao<Usuario> dao = new UsuarioDao();
            dao.create(usuario);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.usuario.bo.incluir", ex);
        }
    }

    private void verificarNull(Object obj) throws SepeException {
        if (obj == null) {
            throw new SepeException("erro.usuario.bo.null");
        }
    }

    private void verificarLoginExistente(Usuario usuario) throws SepeException {
        try {
            UsuarioDao dao;
            dao = new UsuarioDao();
            Usuario usuarioBD = dao.verificarLoginExistente(usuario);

            if (usuarioBD != null && usuarioBD.getId() != usuarioBD.getId()) {
                throw new DataAccessLayerException("erro.usuario.dao.usuario.duplicado");
            }
        } catch (DataAccessLayerException e) {
            throw new SepeException("erro.usuario.login.existente");
        }

    }

    /**
     * Alterar os dados do usário.
     * @param usuario O usuário a ser alterado.
     */
    public void alterar(Usuario usuario) throws SepeException {
        verificarNull(usuario);
        if (isAdminUser(usuario) && !isAdminUser(getSepe().getUsuarioSessao())) {
            throw new SepeException("erro.usuario.bo.isAdminUser");
        }
        verificarLoginExistente(usuario);
        try {
            verificarTamMin("login", usuario.getLogin());
            verificarTamMin("nome", usuario.getNome());

            Dao<Usuario> dao = new UsuarioDao();
            dao.update(usuario);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.usuario.bo.alterar", ex);
        }
    }

    /**
     * Exclui o usuário do sistema.
     * @param usuario O usuário a ser excluído.
     */
    public void excluir(Usuario usuario) throws SepeException {
        if (isAdminUser(usuario)) {
            throw new SepeException("erro.usuario.bo.excluir.isAdminUser");
        }
        try {
            Dao<Usuario> dao = new UsuarioDao();
            dao.delete(usuario);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.usuario.bo.excluir", ex);
        }
    }

    /**
     * Exclui o usuário do sistema.
     * @param id O identificador do usuário a ser excluído.
     */
    public void excluir(Integer id) throws SepeException {
        if (isAdminUser(id)) {
            throw new SepeException("erro.usuario.bo.excluir.hasAdminUser");
        }
        try {
            Dao<Usuario> dao = new UsuarioDao();
            dao.delete(id);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.usuario.bo.excluir.id", ex);
        }
    }

    /**
     * Pesquisar usuário filtrando por login e nome.
     * @param login O login do usuário.
     * @param nome O nome do usuário.
     */
    public List<Usuario> pesquisar(String login, String nome, Perfil perfil) throws SepeException {
        try {
           // verificarTamMin("login", login);
            //verificarTamMin("nome", nome);
            UsuarioDao dao = new UsuarioDao();
            return dao.pesquisar(login, nome, perfil);
        } catch (DataAccessLayerException ex) {
            logger.error(ex.getMessage(), ex);
            throw new SepeException("erro.usuario.bo.pesquisar", ex);
        }
    }

    private boolean isAdminUser(Integer id) throws SepeException {
        if (id != null && id.equals(ADMIN)) {
            return true;
        }
        return false;
    }

    private boolean isAdminUser(Usuario usuario) throws SepeException {
        if (usuario != null) {
            return isAdminUser(usuario.getId());
        }
        return false;
    }

    /**
     *
     * @param texto
     * @throws br.cesed.lti.Sepe.bo.SepeException
     */
    private void verificarTamMin(String att, String texto) throws SepeException {
        if (texto == null || texto.equals(STRING_VAZIO)
                || texto.length() < TAMANHO_MINIMO) {
            String[] parametros = {att, TAMANHO_MINIMO + ""};
            throw new SepeException("erro.usuario.bo.pesquisar.tam.min", parametros);
        }
    }
}
